namespace :cron do
  desc "update account level according to the site setting"
  task :account_level => :environment do
    configs = 
      SiteSetting.get_configs :recommander_level_stay, :recommander_level_promotion,
        :recommander_from_day, :recommander_gap_days

    # check configs: we must have every config, not nill
    configs.each do |k, v|
      abort("Setting is not complete") unless v
      puts "#{k}: #{v}"
    end

    # check whether we should do promotion?
    day_away = Date.today.mjd - Date.parse(configs[:recommander_from_day]).mjd

    abort("not need to upgrade") if day_away <= 0
    abort("not need to upgrade") unless (day_away % configs[:recommander_gap_days].to_i == 0)
    
    before_date = Date.today.strftime('%Y-%m-%d')
    after_date = configs[:recommander_gap_days].to_i.days.ago.strftime('%Y-%m-%d')

    recommands = 
      Recommand.after_date(after_date).before_date(before_date)
        .select(['recommander_id', 'COUNT(id) AS total'])
        .group(:recommander_id)
        .includes(recommander: :account_group)

    # remove non-exist recommander
    recommands.delete_if { |r| r.recommander.nil? || !r.recommander.is_recommander }

    all_recommander = Account.where(is_recommander: true).includes(:account_group)
    current_recommander = recommands.map(&:recommander_id).uniq
    all_recommander.each do |r|
      unless current_recommander.include? r.id
        recommand = Recommand.new(recommander_id: r.id)
        recommand.recommander = r
        recommands << recommand
      end
    end

    recommands.each do |r|
      recommander = r.recommander
      recommander.level_change = Account.determine_level_change r.respond_to?(:total) ? r.total.to_i : 0, 
        configs[:recommander_level_stay].to_i, configs[:recommander_level_promotion].to_i
      recommander.level_after =  Account.determine_level_after recommander.account_group.levels, recommander.level, recommander.level_change
      recommander.level_after ||= recommander.level_before || 1.0

      if recommander.update_column(:level, recommander.level_after)
        puts "Success: #{recommander.name}[#{recommander.mobile_number}], #{recommander.level} => #{recommander.level_change} => #{recommander.level_after}"
      end
    end
  end
end